<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="umsroot.css">
<TITLE>
Using the macros
</TITLE>
</HEAD>
<BODY >
<A HREF="umsroot067.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot066.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot069.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc165">12.2</A>&nbsp;&nbsp;Using the macros</H2><UL>
<LI><A HREF="umsroot068.html#toc99">Source Annotation-aware macro transformations</A>
</UL>

<A NAME="usingmacros"></A>

The following declarations and built-ins control macro expansion:
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B>local macro(+TermClass, +TransPred, +Options)</B><DD CLASS="dd-description">
define a macro for the given <I>TermClass</I>. The transformation will
be performed by the predicate <I>TransPred</I>.
<DT CLASS="dt-description"><B>export macro(+TermClass, +TransPred, +Options)</B><DD CLASS="dd-description">
as above, but available to other modules.
<DT CLASS="dt-description"><B>erase_macro(+TermClass, +Options)</B><DD CLASS="dd-description">
erase a currently defined macro for <I>TermClass</I>. This can only be done
in the module where the definition was made.
<DT CLASS="dt-description"><B>current_macro(?TermClass, ?TransPred, ?Options, ?Module)</B><DD CLASS="dd-description">
retrieve information about currently defined visible macros.
</DL>
Macros are selectively applied only to terms of the specified class.
<I>TermClass</I> can take two forms:
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B>Name/Arity</B><DD CLASS="dd-description"> transform all terms with the specified functor
<A NAME="@default656"></A>
<A NAME="@default657"></A>
<DT CLASS="dt-description"><B>type(Type)</B><DD CLASS="dd-description"> transform all terms of the specified type, where Type
is one of <TT>compound, string, integer, rational, float, breal, atom,
goal</TT><SUP><A NAME="text16" HREF="umsroot066.html#note16">1</A></SUP>.
</DL>
The +TransPred argument specifies the predicate that will perform the
transformation. It has to be either of arity 2 or 3 and should have the form:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
trans_function(OldTerm, NewTerm [, Module]) :- ... .
</PRE></BLOCKQUOTE>
or it can be source annotation aware, and be of arity 4 or 5, as follows:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
trans_function(OldTerm, NewTerm, OldAnn, NewAnn [, Module]) :- ... .
</PRE></BLOCKQUOTE>
At transformation time, the system will call <I>TransPred</I> in the module
where <A HREF="../bips/kernel/syntax/macro-3.html"><B>macro/3</B></A><A NAME="@default658"></A> was invoked.
The term to transform is passed as the first argument, the second is a free
variable which the transformation predicate should bind to the transformed
term. In the case of the source annotation aware version of TransPred, if
the term was read in by read_annotated/2,3, the annotated version of the
term to transformed is passed in the third argument, and the transformation
should bind the fourth argument to the annotated transformed term;
otherwise, if no source annotation information is available, the third
argument is passed in as a free variable, and the transformation should not
bind the fourth argument. In both TransPred cases, the optional last
argument is the module where the term was being read in. See
section&nbsp;<A HREF="#annotated">12.2.1</A> for more details on annotated terms.<BR>
<BR>
<I>Options</I> is a list which may be empty (in this case the macro defaults
to a local read term macro) or contain specifications from
the following categories:
<UL CLASS="itemize"><LI CLASS="li-itemize">
mode
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<A NAME="@default659"></A>
<B>read:</B><DD CLASS="dd-description"> This is a read macro and shall be applied after reading a
term (default).<BR>
<BR>
<A NAME="@default660"></A>
<DT CLASS="dt-description"><B>write:</B><DD CLASS="dd-description"> This is a write macro and shall be applied before printing
a term. 
</DL><BR>
<BR>
<LI CLASS="li-itemize">type
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<A NAME="@default661"></A>
<B>term:</B><DD CLASS="dd-description"> Transform all terms (default).<BR>
<BR>
<A NAME="@default662"></A>
<DT CLASS="dt-description"><B>clause:</B><DD CLASS="dd-description"> Transform only if the term is a program clause,
i.e. inside <A HREF="../bips/kernel/compiler/compile-1.html"><B>compile/1</B></A><A NAME="@default663"></A>,
etc.<SUP><A NAME="text17" HREF="umsroot066.html#note17">2</A></SUP> 
Write macros are applied using the 'C' option in the <A HREF="../bips/kernel/ioterm/printf-2.html"><B>printf/2</B></A><A NAME="@default667"></A> predicate.<BR>
<BR>
<A NAME="@default668"></A>
<DT CLASS="dt-description"><B>goal:</B><DD CLASS="dd-description"> Goal-read-macros are transformed only if the term is a
subgoal in the body of a program clause.
Goal-write macros are applied using the 'G' option in the
<A HREF="../bips/kernel/ioterm/printf-2.html"><B>printf/2</B></A><A NAME="@default669"></A> predicate.
</DL><BR>
<BR>
<LI CLASS="li-itemize">additional specification
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<A NAME="@default670"></A>
<B>protect_arg:</B><DD CLASS="dd-description"> Disable transformation of subterms (optional).
<A NAME="@default671"></A>
<DT CLASS="dt-description"><B>top_only:</B><DD CLASS="dd-description"> Consider only the whole term, not subterms (optional).
</DL>
</UL>
The following shorthands exist:
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B>local/export portray(+TermClass, +TransPred, +Options)</B><DD CLASS="dd-description">
 <A HREF="../bips/kernel/syntax/portray-3.html"><B>portray/3</B></A><A NAME="@default672"></A>
 is like
 <A HREF="../bips/kernel/syntax/macro-3.html"><B>macro/3</B></A><A NAME="@default673"></A>,
 but the write-option is implied.
<DT CLASS="dt-description"><B>inline(+PredSpec, +TransPred)</B><DD CLASS="dd-description">
 <A HREF="../bips/kernel/compiler/inline-2.html"><B>inline/2</B></A><A NAME="@default674"></A>
 is the same as a goal-read-macro. The visibility is inherited
 from the transformed predicate.
</DL>
Here is an example of a conditional read macro:
<BLOCKQUOTE CLASS="quote">
<PRE CLASS="verbatim">
[eclipse 1]: [user].
 trans_a(a(X,Y), b(Y)) :-    % transform a/2 into b/1,
        number(X),           % but only under these
        X &gt; 0.               % conditions

:- local macro(a/2, trans_a/2, []).
  user       compiled traceable 204 bytes in 0.00 seconds

yes.
[eclipse 2]: read(X).
        a(1, hello).

X = b(hello)                 % transformed
yes.
[eclipse 3]: read(X).
        a(-1, bye).

X = a(-1, bye)               % not transformed
yes.
</PRE></BLOCKQUOTE>
If the transformation function fails, the term is not transformed. Thus, 
<B>a(1, zzz)</B> is transformed into <B>b(zzz)</B> but <B>a(-1, zzz)</B> 
is not transformed.
The arguments are transformed bottom-up. It is possible to protect the 
subterms of a transformed term by specifying the flag <TT>protect_arg</TT>.<BR>
<BR>
A term can be protected against transformation by quoting it with 
the &#8220;protecting functor&#8221; (by default it is <B>no_macro_expansion/1</B>):
<A NAME="@default675"></A>
<A NAME="@default676"></A>
<BLOCKQUOTE CLASS="quote">
<PRE CLASS="verbatim">
[eclipse 4]: read(X).
        a(1, no_macro_expansion(a(1, zzz))).
X = b(a(1, zzz)).
</PRE></BLOCKQUOTE>
Note that the protecting functor is itself defined as a macro:
<BLOCKQUOTE CLASS="quote"> <PRE CLASS="verbatim">
trprotect(no_macro_expansion(X), X).
:- export macro(no_macro_expansion/1, trprotect/2, [protect_arg]).
</PRE></BLOCKQUOTE>
A local macro is only visible in the module where it has been defined.
When it is defined as exported, then it is copied to all
other modules that contain a
<A HREF="../bips/kernel/modules/use_module-1.html"><B>use_module/1</B></A><A NAME="@default677"></A> or
<A HREF="../bips/kernel/modules/import-1.html"><B>import/1</B></A><A NAME="@default678"></A>
for this module.
The transformation function should also be exported in this case.
There are a few global macros predefined by the system, e.g. for
<TT>-</TT><TT>-&gt;/2</TT> (grammar rules, see below) or <TT>with/2</TT> and <TT>of/2</TT>
(structure syntax, see section <A HREF="umsroot022.html#chapstruct">5.1</A>).
These predefined macros can be hidden by local macro definitions.<BR>
<BR>
<A NAME="@default679"></A>
The global flag <B>macro_expansion</B> can be used to disable
macro expansion globally, e.g. for debugging purposes.
Use <TT>set_flag(macro_expansion, off)</TT> to do so.<BR>
<BR>
The next example shows the use of a type macro. Suppose we want to represent
integers as s/1 terms:
<BLOCKQUOTE CLASS="quote"> <PRE CLASS="verbatim">
[eclipse 1]: [user].
 tr_int(0, 0).
 tr_int(N, s(S)) :- N &gt; 0, N1 is N-1, tr_int(N1, S).
 :- local macro(type(integer), tr_int/2, []).

yes.
[eclipse 2]: read(X).
        3.

X = s(s(s(0)))
yes.
</PRE></BLOCKQUOTE>
When we want to convert the s/1 terms back to normal integers so that they
are printed in the familiar form, we can use a write macro.
Note that we first erase the read macro for integers, otherwise we would get
unexpected effects since all integers occurring in the definition of
tr_s/2 would turn into s/1 structures:
<BLOCKQUOTE CLASS="quote"> <PRE CLASS="verbatim">
[eclipse 3]: erase_macro(type(integer)).

yes.
[eclipse 4]: [user].
 tr_s(0, 0).
 tr_s(s(S), N) :- tr_s(S, N1), N is N1+1.
 :- local macro(s/1, tr_s/2, [write]).

yes.
[eclipse 2]: write(s(s(s(0)))).
3
yes.
</PRE></BLOCKQUOTE>
<A NAME="toc99"></A>
<H3 CLASS="subsection"><A NAME="htoc166">12.2.1</A>&nbsp;&nbsp;Source Annotation-aware macro transformations</H3>
<A NAME="annotated"></A>
When the macro transformation predicate has 4 or 5 arguments, it is termed
source annotation aware, and the extra
arguments are used to specify how source information from the 
original term should be mapped to the transformed term.<BR>
<BR>
An annotated term provides the source information about a term. It
is structurally similar to the original term and
contains all information about the term, plus additional type information,
variable names, and source position annotations for all subterms.<BR>
<BR>
The structure of the descriptive terms is as follows:
<PRE CLASS="verbatim">    
        :- export struct(annotated_term(
                term,                   % var, atomic or compound
                type,                   % term type (see below)
                file,                   % source file name (atom)
                line,                   % source line (integer)
                from, to                % source position (integers)
                ...
        )).
</PRE>
The type-field describes the type of the original term and provide type
information similar to those used in <A HREF="../bips/kernel/typetest/type_of-2.html"><B>type_of/2</B></A><A NAME="@default680"></A>, except that they convey additional information about variables and <TT>end_of_file</TT>.<BR>
<BR>
In the case of atomic terms and variables, the term-field simply
 contains the plain original term. For compound terms, the term-field
 contains a structure whose functor is the functor of the plain term,
 but whose arguments are annotated versions of the plain term arguments.<BR>
<BR>
For example, the annotated term representing the source term <TT>foo(bar, X, _, 3)</TT> is:
<PRE CLASS="verbatim">
        annotated_term(foo(
            annotated_term(bar, atom, ...),
            annotated_term(X, var('X'), ...),
            annotated_term(_, anonymous, ...),
            annotated_term(3, integer, ...)),
        compound, ...)
</PRE>
The file/line/from/to-fields of an annotated term describe the
"source position" of the term, as follows:
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B>file</B><DD CLASS="dd-description">
 The canonical file name of the source file (an atom), or the
 empty atom &#8221; if the source is not a file or not known.<BR>
<BR>
<DT CLASS="dt-description"><B>line</B><DD CLASS="dd-description">
 The line number in the source stream (positive integer).<BR>
<BR>
<DT CLASS="dt-description"><B>from, to</B><DD CLASS="dd-description">
 The exact term position as integer offsets in the source stream,
 starting at from and ending at to-1.
</DL>
The extra arguments for the transformation predicate are a pair of
annotated terms for the original and transformed term. The predicate will
be supplied with the annotated term for the original term if available,
and the predicate is responsible for specifying the annotated term for the
transformed term &ndash; the structure of the transformed annotated term must
match the annotated term structure expected for the transformed term. If
no annotated information is available, the original annotated term will be
a variable, and the predicate must not bind the transformed annotated term.<BR>
<BR>
For an example, here is a source annotation aware version of the previous
 <CODE>trans_a/2</CODE> example:
<PRE CLASS="verbatim">
[eclipse 1]: [user].
...

 trans_a(a(X,Y), b(Y), AnnA, AnnTrans) :-    
        number(X),           
        X &gt; 0,
        ( var(AnnA) -&gt;
              true      % no source information, leave AnnTrans as var
        ;
              AnnA = annotated_term{term:a(_AnnX, AnnY),
                                    file:File, line:Line,
                                    from:From,to:To},
              AnnTrans = annotated_term{term:b(AnnY),
                                    type: compound,
                                    file:File, line:Line,
                                    from:From,to:To}
         ).               

:- local macro(a/2, trans_a/4, []).

Yes (0.23s cpu)
[eclipse 2]: read_annotated(user, X, Y).   
 a(3,bar(X)).

X = b(bar(X))
Y = annotated_term(b(annotated_term(bar(annotated_term(X, var('X'), user, 18, 654, 655)), compound, user, 18, 650, 654)), compound, user, 18, 646, 648)

</PRE>
In the example, the main functor of the transformed predicate, <CODE>b/1</CODE>,
inherits the annotation information for the original tern's principle
functor, <CODE>a/2</CODE>. The argument Y in the transformed term takes the 
annotation information from the corresponding argument in the original
term. <BR>
<BR>
The source annotation aware transformation predicate facility is provided to
 allow the user to detail how the subterms of the original term is mapped
 to the transformed term. Without this extra information, the whole of
 the transformed term is given the source information (source position,
 source file etc.) of the original source term. This extra information is
 useful when the subterms are goals, because without the extra
 information, source tracing of these goals during debugging will not be
 done.<BR>
<BR>
<HR>
<A HREF="umsroot067.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot066.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot069.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
